package net.wexoo.onlinedivelog.dal;

import static org.apache.log4j.Logger.getLogger;

import java.io.Serializable;
import java.util.List;

import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

public abstract class AbstractSessionDAO<T extends Serializable> implements IDAO<T> {

  protected Class<T> clazz;

  // @Autowired
  SessionFactory sessionFactory;

  @Override
  public void setClazz(final Class<T> clazzToSet) {
    this.clazz = clazzToSet;
  }

  @Override
  @SuppressWarnings("unchecked")
  public T getBeanById(final int id) {
    //    Preconditions.checkArgument( id != null );
    return (T) getCurrentSession().get(this.clazz, id);
  }

  @Override
  @SuppressWarnings("unchecked")
  public List<T> getAll() {
    return getCurrentSession().createQuery("from " + getBeanClassName()).list();
  }

  @Override
  @SuppressWarnings("unchecked")
  public List<T> getAll(SortParam sortParam, Integer first, Integer count) {
    StringBuilder queryBuilder = new StringBuilder("from ");
    queryBuilder.append(getBeanClassName());

    if (sortParam != null) {
      queryBuilder.append(" order by ");
      queryBuilder.append(sortParam.getProperty());
      queryBuilder.append(sortParam.isAscending() ? " asc" : " desc");
    }

    Query q = getCurrentSession().createQuery(queryBuilder.toString());

    if (first != null)
      q.setFirstResult(first);
    if (count != null)
      q.setMaxResults(count);

    return q.list();
  }

  @Override
  public T saveOrUpdate(final T entity) {
    //    Preconditions.checkNotNull( entity );
    getCurrentSession().persist(entity);
    return entity;
  }

  public void update( final T entity ){
    //    Preconditions.checkNotNull( entity );
    getCurrentSession().merge(entity);
  }

  @Override
  public boolean delete(final T entity) {
    //    Preconditions.checkNotNull( entity );
    try {
      getCurrentSession().delete(entity);
    } catch (Exception e) {
      getLogger(getClass()).error("Error when removing entity!\n" + e.toString());
      return false;
    }
    return true;
  }

  public void deleteById(final int entityId) {
    final T entity = this.getBeanById(entityId);
    //    Preconditions.checkState( entity != null );
    delete(entity);
  }

  @Override
  public Long getCount() {
    return (Long) getCurrentSession().createQuery("select count(*) from " + getBeanClassName()).uniqueResult();
  }

  protected final Session getCurrentSession(){
    return sessionFactory.getCurrentSession();
  }
}
